package yiran.agift.lang;

import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import yiran.agift.AGift;
import yiran.agift.output.Logger;


import java.io.File;
import java.util.Collections;
import java.util.List;

public class LangHelper {
    private static FileConfiguration langConfig;
    private static AGift plugin;

    /**
     * 初始化语言帮助类
     *
     * @param plugin 插件实例，用于初始化LangHelper类
     * <p>
     * 此方法的作用是将插件实例赋值给LangHelper类中的静态变量plugin，
     * 并调用reload方法重新加载语言配置确保插件的语言功能能够正常使用
     * <p>
     * 为什么这么做：
     * 通过传递插件实例，可以使得LangHelper类能够访问插件特有的资源，
     * 比如配置文件、语言文件等，这对于实现国际化和本地化支持至关重要
     * <p>
     * 注意事项：
     * - 此方法应在插件启用时调用，以确保所有语言相关功能可以立即使用
     * - 调用此方法前应确保plugin参数不为null，否则可能导致运行时错误
     */
    public static void init(AGift plugin) {
        LangHelper.plugin = plugin;
        reload();
    }


    /**
     * 重新加载语言文件
     * 此方法旨在重新加载插件的语言配置，以便在插件运行时更新语言设置
     */
    public static void reload() {
        // 检查插件对象和插件的数据文件夹是否存在，如果任一条件不满足，则记录错误信息并返回
        if (plugin == null || plugin.getDataFolder() == null) {
            Logger.error("LangHelper 未初始化或 dataFolder 为空");
            return;
        }

        try {
            // 从配置文件中获取语言设置，如果未设置则默认使用"zh_CN"
            String langFile = plugin.getConfig().getString("language", "zh_CN") + ".yml";
            // 构造语言文件的路径和名称
            File file = new File(plugin.getDataFolder(), "lang/" + langFile);

            // 如果语言文件不存在，则从资源中复制一个到dataFolder
            if (!file.exists()) {
                plugin.saveResource("lang/" + langFile, false);
            }

            // 加载语言文件到langConfig中，以便后续使用
            langConfig = YamlConfiguration.loadConfiguration(file);
        } catch (Exception e) {
            // 如果在加载语言文件过程中发生异常，则记录错误信息
            Logger.error("语言文件加载失败: " + e.getMessage());
        }
    }

    /**
     * 根据路径获取配置字符串，并支持格式化
     *
     * @param path 配置项的路径
     * @param args 用于格式化字符串的参数
     * @return 根据路径获取的配置字符串，如果配置项为空则返回默认值
     */
    public static String getString(String path, Object... args) {
        // 检查语言配置是否为空，如果为空则返回错误信息
        if (langConfig == null) return "LANG_CONFIG_NULL";

        // 尝试从语言配置中获取指定路径的字符串
        String message = langConfig.getString(path);
        // 如果未找到对应的配置项，则返回缺失键的错误信息
        if (message == null) {
            return "MISSING_KEY: " + path;
        }
        // 使用提供的参数格式化字符串，并返回
        return String.format(message, args);
    }


    /**
     * 根据配置路径获取字符串列表
     * 该方法用于从一个语言配置对象中获取与指定路径对应的字符串列表如果语言配置对象为空，
     * 则返回一个包含"LANG_CONFIG_NULL"的列表如果指定路径没有对应的配置项或配置项为空列表，
     * 则返回一个包含"MISSING_KEY: [path]"的列表
     *
     * @param path 配置项的路径
     * @return 与路径对应的字符串列表，可能包含错误信息
     */
    public static List<String> getStringList(String path) {
        // 检查语言配置对象是否为空
        if (langConfig == null) return Collections.singletonList("LANG_CONFIG_NULL");

        // 从语言配置中获取与路径对应的字符串列表
        List<String> messages = langConfig.getStringList(path);
        // 检查获取的列表是否为空或为null
        if (messages == null || messages.isEmpty()) {
            // 返回包含缺失键信息的列表
            return Collections.singletonList("MISSING_KEY: " + path);
        }
        // 返回获取的字符串列表
        return messages;
    }


    /**
     * 根据键获取国际化消息，并用指定的参数替换消息中的占位符
     * 如果配置为空，返回特定错误消息 如果键不存在，返回缺失键的消息
     * 如果参数数量与消息中预期的数量不匹配，记录警告日志
     * 如果消息格式化失败，记录错误日志并返回未格式化的消息
     *
     * @param key 国际化消息的键
     * @param args 替换消息中占位符的实际参数
     * @return 格式化后的消息或错误/警告信息
     */
    public static String getSafeString(String key, Object... args) {
        // 检查语言配置是否已初始化
        if (langConfig == null) return "LANG_CONFIG_NULL";

        // 尝试从配置中获取消息模板
        String message = langConfig.getString(key);
        // 如果消息模板不存在，返回缺失键的信息
        if (message == null) {
            return "MISSING_KEY: " + key;
        }

        // 计算预期参数数量
        long expectedArgs = message.chars().filter(ch -> ch == '%').count();

        // 参数数量不匹配时，记录警告日志
        if (expectedArgs != args.length) {
            Logger.warn("参数数量不匹配: " + key + " 预期 " + expectedArgs + " 实际 " + args.length);
        }

        // 尝试格式化消息，如果失败，记录错误日志并返回未格式化的消息
        try {
            return String.format(message, args);
        } catch (Exception e) {
            Logger.error("格式化错误: " + key + " - " + e.getMessage());
            return message + " (格式化失败)";
        }
    }

}

